// 作者: du白
// 邮箱: weichen0716@163.com

using System;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Generic;
using Newtonsoft.Json;

namespace WebPrinter.Library.DaQu.Util
{
    /// <summary>
    /// 大趋请求工具类
    /// </summary>
    public static class DaQuRequestUtils
    {
        private static readonly HttpClient _httpClient;
        private static readonly JsonSerializerSettings _jsonSettings;

        static DaQuRequestUtils()
        {
            _httpClient = new HttpClient
            {
                Timeout = TimeSpan.FromSeconds(5)
            };
            _jsonSettings = new JsonSerializerSettings
            {
                DateFormatString = "yyyy-MM-dd HH:mm:ss",
                NullValueHandling = NullValueHandling.Ignore
            };
        }

        /// <summary>
        /// 发起POST请求
        /// </summary>
        /// <typeparam name="R">响应数据类型</typeparam>
        /// <typeparam name="P">请求数据类型</typeparam>
        /// <param name="url">请求地址</param>
        /// <param name="body">请求体</param>
        /// <param name="appId">AppId</param>
        /// <param name="appSecret">AppSecret</param>
        /// <returns>响应结果</returns>
        public static async Task<R> PostAsync<R, P>(string url, P body, string appId, string appSecret)
        {
            string requestBodyStr = JsonConvert.SerializeObject(body, _jsonSettings);
            var headers = GetHeader(requestBodyStr, appId, appSecret);
            using var request = new HttpRequestMessage(HttpMethod.Post, url)
            {
                Content = new StringContent(requestBodyStr, Encoding.UTF8, "application/json")
            };
            foreach (var kv in headers)
            {
                request.Headers.Add(kv.Key, kv.Value);
            }
            using var response = await _httpClient.SendAsync(request);
            response.EnsureSuccessStatusCode();
            string responseStr = await response.Content.ReadAsStringAsync();
            return JsonConvert.DeserializeObject<R>(responseStr, _jsonSettings);
        }

        /// <summary>
        /// 生成带签名的请求头
        /// </summary>
        /// <param name="requestBodyStr">请求体字符串</param>
        /// <param name="appId">AppId</param>
        /// <param name="appSecret">AppSecret</param>
        /// <returns>请求头字典</returns>
        public static Dictionary<string, string> GetHeader(string requestBodyStr, string appId, string appSecret)
        {
            long stime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
            string uid = Guid.NewGuid().ToString();
            string originContext = uid + appId + stime + appSecret;
            if (!string.IsNullOrEmpty(requestBodyStr))
            {
                originContext += requestBodyStr;
            }
            string sign = GetMd5(originContext);
            return new Dictionary<string, string>
            {
                { "appid", appId },
                { "uid", uid },
                { "stime", stime.ToString() },
                { "sign", sign }
            };
        }

        /// <summary>
        /// 计算字符串的MD5值
        /// </summary>
        private static string GetMd5(string input)
        {
            using var md5 = MD5.Create();
            var bytes = Encoding.UTF8.GetBytes(input);
            var hash = md5.ComputeHash(bytes);
            var sb = new StringBuilder();
            foreach (var b in hash)
            {
                sb.Append(b.ToString("x2"));
            }
            return sb.ToString();
        }
    }
}